#!/usr/local/bin/node

/**
 * This script is responsible for creating the final build of all the project's
 * JavaScript.
 *
 * 1. Creates a prebuild of internal/view/static/js/app.js
 * 2. Creates a prebuild of all *.inc.js files in internal/view/web
 * 3. Combines the two prebuilds into a final build, minifies it, and stores
 *    it in internal/view/static/build/app.min.js
 *
 * This script generates temporal files in the tmp directory.
 */

import path from "node:path";
import { fileURLToPath } from "node:url";
import fse from "fs-extra";
import * as esbuild from "esbuild";
import { glob } from "glob";

// Obtains the project's root directory
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const rootDir = path.join(__dirname, "..");

async function prebuildApp() {
  const entryFile = path.join(rootDir, "./internal/view/static/js/app.js");
  const outFile = path.join(rootDir, "./tmp/prebuild-app.js");

  try {
    await esbuild.build({
      entryPoints: [entryFile],
      bundle: true,
      minify: false,
      outfile: outFile,
      format: "iife",
    });
  } catch (error) {
    console.error("Error prebuilding app.js:", error);
  }
}

async function prebuildIncludedFiles() {
  const alpineGlob = path.join(rootDir, "./internal/view/web/**/*.inc.js");
  const tempFile = path.join(rootDir, "./tmp/prebuild-incs.js");

  try {
    const alpineFiles = await glob(alpineGlob);

    let outFileContent = `// This file is auto-generated by ${__filename}. DO NOT EDIT.\n\n`;

    for (const file of alpineFiles) {
      const content = await fse.readFile(file, "utf-8");
      outFileContent += content + "\n";
    }

    await fse.outputFile(tempFile, outFileContent);
  } catch (error) {
    console.error("Error prebuilding *.inc.js files:", error);
  }
}

async function mergePrebuilds() {
  const prebuilds = [
    path.join(rootDir, "./tmp/prebuild-app.js"),
    path.join(rootDir, "./tmp/prebuild-incs.js"),
  ];

  const outFile = path.join(rootDir, "./tmp/prebuild.js");

  try {
    let outFileContent = "";

    for (const file of prebuilds) {
      const content = await fse.readFile(file, "utf-8");
      outFileContent += content + "\n\n";
    }

    await fse.outputFile(outFile, outFileContent);
  } catch (error) {
    console.error("Error combining prebuilds:", error);
  }
}

async function build() {
  const entryFile = path.join(rootDir, "./tmp/prebuild.js");
  const outFile = path.join(rootDir, "./internal/view/static/build/app.min.js");

  try {
    await esbuild.build({
      entryPoints: [entryFile],
      bundle: true,
      minify: true,
      outfile: outFile,
      format: "iife",
    });

    console.log("JavaScript builded successfully");
  } catch (error) {
    console.error("Error creating JavaScript build:", error);
  }
}

await prebuildApp();
await prebuildIncludedFiles();
await mergePrebuilds();
await build();
